﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UBlockly.UI;
using UnityEngine.AI;
using UBlockly.Compotent;

namespace UBlockly
{
    public static class UBlockExtension
    {
        public static void SetToTop(LinkedListNode<Node> node)
        {
            var list = node.List;
            if (list != null)
            {
                var p = list.First;
                while (p != null)
                {
                    p.Value.Block.transform.SetAsLastSibling();
                    p = p.Next;
                }
            }
            else
            {
                node.Value.Block.transform.SetAsLastSibling();
            }
        }

        /// <summary>
        /// 按物理排列
        /// </summary>
        /// <param name="list"></param>
        public static void PhysicSort(this LinkedList<Node> list)
        {
            if (list == null || list.Count == 0)
                return;
            var p = list.First;
            var index = p.Value.Block.transform.GetSiblingIndex();
            var preposition = p.Value.Block.transform.localPosition;
            var parent = p.Value.Block.transform.parent;
            float height = p.Value.Block.GetSize().y;
            p = p.Next;
            while (p != null)
            {
                p.Value.Block.transform.SetParent(parent);
                p.Value.Block.transform.SetSiblingIndex(++index);
                height = height / 2 + p.Value.Block.GetSize().y / 2;
                preposition = preposition - new Vector3(0, height + BlockGraphicSize.BlockVertialSpace, 0);
                p.Value.Block.transform.localPosition = preposition;
                height = p.Value.Block.GetSize().y;
                p = p.Next;
            }
        }

        public static int GetLength(LinkedList<Node> list)
        {
            if (list == null || list.Count == 0)
                return 0;
            var len = list.Last.Value.Block.transform.localPosition.y - list.First.Value.Block.transform.localPosition.y;
            len = Mathf.Abs(len);
            len += (list.First.Value.Block.GetSize().y / 2.0f + list.Last.Value.Block.GetSize().y / 2.0f);
            return (int)len;
        }

        /// <summary>
        /// 判断两个矩形是否相交
        /// </summary>
        /// <param name="r1"></param>
        /// <param name="r2"></param>
        /// <returns></returns>
        public static bool IsRectAcross(Rect r1, Rect r2)
        {
            return r1.Overlaps(r2) || r2.Overlaps(r1);
        }

        public static bool IsRecttransAcross(RectTransform r1, RectTransform r2)
        {
            if (r1 == null || r2 == null)
                return false;
            return r1.WorldRect().Overlaps(r2.WorldRect()) || r2.WorldRect().Overlaps(r1.WorldRect());
        }

        public static bool IsAcross(RectTransform r1, Vector2 point)
        {
            Vector2 from = (Vector2)r1.position + r1.rect.position;
            Vector2 to = from + r1.rect.size;
            return point.x > from.x && point.y > from.y && point.x < to.x && point.y < to.y;
        }

        public static Rect WorldRect(this RectTransform rectTransform)
        {
            Vector2 sizeDelta = rectTransform.sizeDelta;
            float rectTransformWidth = sizeDelta.x * rectTransform.lossyScale.x;
            float rectTransformHeight = sizeDelta.y * rectTransform.lossyScale.y;

            Vector3 position = rectTransform.position;
            var rr = new Rect(position.x + rectTransformWidth * rectTransform.pivot.x, position.y - rectTransformHeight * rectTransform.pivot.y, rectTransformWidth, rectTransformHeight);
            //Debug.Log(rectTransform.parent.name + ":" + rr);
            return rr;
        }

        /// <summary>
        /// 拖动一个链时，把头以下所有节点放到头的子节点下
        /// </summary>
        /// <param name="dragBlock"></param>
        public static void HandlerBeginDragBlock(BlockObject dragBlock)
        {
            var list = dragBlock.Node.List;
            if (list != null)
            {
                var p = dragBlock.Node.Next;
                var pos = dragBlock.Position;
                float dheight = dragBlock.GetSize().y;
                while (p != null)
                {
                    p.Value.Block.transform.SetParent(dragBlock.transform);
                    dheight = dheight / 2 + p.Value.Block.GetSize().y / 2;
                    pos = pos - new Vector3(0, dheight + BlockGraphicSize.BlockVertialSpace, 0);
                    p.Value.Block.SetPosition(pos);
                    dheight = p.Value.Block.GetSize().y;
                    p = p.Next;
                }
            }
        }

        /// <summary>
        /// 拖动结束时还原
        /// </summary>
        /// <param name="dragBlock"></param>
        public static void HandlerEndDragBlock(BlockObject dragBlock)
        {
            var p = dragBlock.Node.Next;
            var parent = dragBlock.Parent;
            while (p != null)
            {
                var pos = p.Value.Block.Position;
                p.Value.Block.transform.SetParent(parent);
                p.Value.Block.SetPosition(pos);
                p = p.Next;
            }
        }

        /// <summary>
        /// 把一个链中的某个开始的所有移除，同时被移除的形成另一个
        /// </summary>
        /// <param name="list"></param>
        /// <param name="node"></param>
        /// <param name="newParent">新链的父节点</param>
        /// <returns></returns>
        public static ULinkedList<Node> Split(this ULinkedList<Node> list, Node node,Transform newParent,ref bool isBreak)
        {
            if (list.First.Value.Id == node.Id)
            {
                isBreak = false;
                return list;
            }

            isBreak = true;
            var p = list.Last;
            var nlist = new ULinkedList<Node>();
            list.MuteNotify();
            nlist.MuteNotify();
            while (p != null && p.Value.Id != node.Id)
            {
                var q = p.Previous;
                list.RemoveLast();
                nlist.AddFirst(p);
                p.Value.Block.transform.SetParent(newParent);
                p = q;
            }
            
            list.RemoveLast();
            nlist.AddFirst(node.Block.Node);
            node.Block.transform.SetParent(newParent);
            Debug.Log($"原来的链{list.First.Value.Id}被分成两个链，新的链{nlist.First.Value.Id}长度为{nlist.Count}");
            list.OpenNoify();
            list.DoNotify();
            nlist.OpenNoify();
            nlist.DoNotify();
            return nlist;
        }

        /// <summary>
        /// 在node节点后面插入blist
        /// </summary>
        /// <param name="list"></param>
        /// <param name="blist"></param>
        /// <param name="node"></param>
        public static void Insert(this LinkedListNode<Node> node, ULinkedList<Node> blist)
        {
            var p = blist.First;
            var list = node.List as ULinkedList<Node>;
            if (list == null)
            {
                list = new ULinkedList<Node>();
                list.AddFirst(node);
            }
            blist.MuteNotify();
            list.MuteNotify();
          //  Debug.Log($"把长度{blist.Count}的链{blist.First.Value.Id}插入长度为{list.Count}的链{list.First.Value.Id}中，插入位置{node.Value.Id}");
            var pre = node;
            while (p != null)
            {
                var q = p.Next;
                blist.RemoveFirst();
                list.AddAfter(pre, p);
                pre = p;
                p = q;
            }
            blist.Clear();
            blist = null;
            list.OpenNoify();
            list.DoNotify();
        }

        public static void Combine(this LinkedList<Node> list, LinkedList<Node> another)
        {
        }

        public static void ForEach(this LinkedList<Node> list, System.Action<Node> action)
        {
            
        }

        public static void ForEachCircle(this LinkedList<Node> list, System.Action<Node> action)
        {
            //此处没有循环，后期加入条件再解决
            foreach (var ll in list)
            {
                action?.Invoke(ll);
            }
        }

        public static Transform FindTransform(this GameObject go,string name, int fromIndex)
        {
            if (go.transform.childCount == 0 || go.transform.childCount < fromIndex)
                return null;
            var max = go.transform.childCount;
            Transform temp = go.transform;
            while (fromIndex < max)
            {
                temp = go.transform.GetChild(fromIndex);
                if (temp.name == name)
                    return temp;
                fromIndex++;
            }
            return null;
        }

    }
}
